package com.lph.health.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.lph.health.config.security.service.UserDetailServiceImpl;
import com.lph.health.dao.SysUserMapper;
import com.lph.health.entity.SysRole;
import com.lph.health.entity.SysUser;
import com.lph.health.entity.TMember;
import com.lph.health.service.SysUserService;
import com.lph.health.utils.*;
import com.lph.health.vo.LoginVo;
import com.lph.health.vo.WxLoginVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;


import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class SysUserServiceImpl implements SysUserService {
    @Autowired
    private TokenUtil tokenUtil;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private UserDetailServiceImpl userDetailsService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Value("${jwt.tokenHead}")
    private String tokenHead;

    @Autowired
    private RedisUtil redisUtil;

    @Value("${wx.appid}")
    private String appid;

    @Value("${wx.secret}")
    private String secret;

    Long userNewId = null;
    /**
     * 登录接口
     * @param loginVo  登录参数： 账号、密码
     * @return
     */
    @Override
    public Result login(LoginVo loginVo) {
        UserDetails userDetails;
        if("2".equals(loginVo.getType())){
            // 邮箱验证码登录
            if(!StringUtil.isNotEmpty(loginVo.getMail()) || !StringUtil.isNotEmpty(loginVo.getCode())) {
                return Result.failure("请填写完整信息");
            }
            // 验证码对比
            Object code = redisUtil.getValue(loginVo.getMail() + "code");
            if(code == null){
                return Result.failure("验证码已过期");
            }
            if(code.equals(loginVo.getCode())){
                return Result.failure("验证码不正确！");
            }
            userDetails = userDetailsService.loadUserByUsername(loginVo.getMail());
        } else {
            if(!StringUtil.isNotEmpty(loginVo.getUserName()) || !StringUtil.isNotEmpty(loginVo.getPassword())) {
                log.info("------" + loginVo.getUserName());
                log.info("------" + loginVo.getPassword());
                return Result.failure("请填写完整信息");
            }
            // 账号密码登录
            log.info("1. 开始账号登录");
            userDetails = userDetailsService.loadUserByUsername(loginVo.getUserName());
            log.info("2. 判断用户是否存在，密码是否正确");
            if(null == userDetails || !passwordEncoder.matches(MD5Util.md5(loginVo.getPassword()), userDetails.getPassword())){
                return Result.failure("账号或密码错误，请重新输入！");
            }
        }
        if(!userDetails.isEnabled()){
            return Result.failure("该账号已禁用，请联系管理员！");
        }
        log.info("登录成功，在security对象存入登录信息");
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);

        log.info("根据登录信息获取token");
        // 借助 jwt 生成token
        String token = tokenUtil.generateToken(userDetails);

        //  向前端返回数据
        Map<String, String> map = new HashMap<>(2);
        map.put("tokenHead", tokenHead);
        map.put("token", token);
        return Result.success("登录成功!", map);
    }

    @Override
    public SysUser findUserName(String userName) {
        return sysUserMapper.findUserName(userName);
    }

    /**
     *
     * @param queryInfo 页码 页数大小 查询内容
     * @return
     */
    @Override
    public Result findPage(QueryInfo queryInfo) {
        log.info("开始权限数据分页--->页码{}, ---{}页数, --->{}查询内容", queryInfo.getPageNumber(), queryInfo.getPageSize(), queryInfo.getQueryString());
        PageHelper.startPage(queryInfo.getPageNumber(), queryInfo.getPageSize());
        Page<SysUser> page = sysUserMapper.findPage(queryInfo.getQueryString());
        long total = page.getTotal();
        log.info("查询的总条数-->{}", total);
        List<SysUser> result = page.getResult();
        log.info("分页列表-->{}", result);
        // 加入角色信息
        result.forEach(item ->{
            item.setRoles(sysUserMapper.findRoles(item.getId()));
            item.setName(item.getUsername());
            item.setPassword(null);
        });
        return PageResult.pageResult(total, result);
    }

    /**
     * 添加用户
     * @param sysUser
     * @return
     */
    @Transactional
    @Override
    public Result insertUser(SysUser sysUser) {
        // 先查询一次角色信息判断其是否存在
        log.info("查询角色信息是否存在");
        SysUser user = sysUserMapper.findByUserName(sysUser.getUsername());

        if(user != null) {
            return Result.failure("用户名已经存在!");
        }
        log.info("密码加密");
        sysUser.setPassword(passwordEncoder.encode(MD5Util.md5(sysUser.getPassword())));
        log.info("1. 添加用户信息");
        sysUserMapper.insertUser(sysUser);
        log.info("2. 添加角色信息");
        List<SysRole> sysRoles = sysUser.getRoles();
        if (sysRoles.size() > 0) {
            sysRoles.forEach(item ->{
                // sysUser.getId()--需要返回新增数据的Id
                sysUserMapper.insertUserRole(sysUser.getId(), item.getId());
            });
            log.info("用户角色添加成功，添加角色数量有:{}", sysRoles.size());
        }
        return Result.success("用户添加成功");
    }

    @Transactional
    @Override
    public Result updateUser(SysUser sysUser) {
        log.info("判断用户名是否重复");
        SysUser user = sysUserMapper.findByUserName(sysUser.getUsername());
        log.info("---------------"+sysUser.getRoles().size());
        if(user == null || sysUser.getUsername().equals(sysUserMapper.findById(sysUser.getId()).getUsername())) {
            if (sysUser.getRoles().size() > 0) {
                log.info("1. 先删除用户角色信息");
                sysUserMapper.deleteRoleByUserId(sysUser.getId());
                log.info("2. 添加用户角色信息");
                sysUser.getRoles().forEach(item ->{
                    sysUserMapper.insertUserRole(sysUser.getId(), item.getId());
                });
            }
            log.info("3. 修改用户角色信息");
            sysUserMapper.updateUser(sysUser);
            return Result.success("修改角色成功");
        } else {
            return Result.failure("用户名已经存在!");
        }
    }

    @Override
    public Result deleteUser(Long id) {
        // 先查询一次角色信息判断其是否存在
        log.info("查询角色信息是否存在");
        SysUser user = sysUserMapper.findById(id);
        if(user == null) {
            return Result.failure("该用户不存在!");
        }
        log.info("查询该角色信息下是否有角色信息");
        if (sysUserMapper.findRoles(user.getId()).size() > 0) {
            return Result.failure("删除失败,该用户下拥有角色信息,请先删除对应的角色信息");
        }
        sysUserMapper.deleteUser(id);
        return Result.success("删除成功");
    }

    /**
     * 修改密码
     * @param email
     * @param password
     */
    @Override
    public void updatePwdByMail(String email, String password) {
        log.info("邮箱修改密码");
        sysUserMapper.upPwdByMail(email, password);
    }

    /**
     * 微信登录
     * @param wxLoginVo
     * @return
     */
    @Transactional
    @Override
    public Result wxlogin(WxLoginVo wxLoginVo) {

        log.info("wxLoginVo"+wxLoginVo);
        //1. 校验验证码输入是否正确
        boolean mailCode1 = redisUtil.hasKey(wxLoginVo.getEmail()+"mailCode");
        log.info("mailCode1"+mailCode1);
        //判断验证码是否存在
        if (!redisUtil.hasKey(wxLoginVo.getEmail()+"mailCode")) {
            return Result.failure("验证码已过期");
        }
        //判断验证码是正确
        String mailCode = redisUtil.getValue(wxLoginVo.getEmail()+"mailCode").toString();
        System.out.println("mailCode"+mailCode);
        if (!mailCode.equals(wxLoginVo.getMsgCode())) {
            return Result.failure("验证码错误");
        }
        //访问微信url
        String url = "https://api.weixin.qq.com/sns/jscode2session";
        //添加参数
        Map<String, String> map = new HashMap<>(16);
        map.put("appid", appid);
        map.put("secret", secret);
        map.put("js_code", wxLoginVo.getCode());
        map.put("grant_type", "authorization_code");
        try {
            //2. 根据请求码获取用户openId
            String response = HttpUtil.getResponse(url, map);
            //将字符串转为Json
            JSONObject object = JSON.parseObject(response);
            //得到openId
            String openId = object.getString("openid");
            //得到sessionKey
            String sessionKey = object.getString("session_key");

            //3. 根据用户输入的邮箱账号去数据库查询是否有该用户 不存在就添加 存在就修改
            SysUser user = sysUserMapper.findByEmail(wxLoginVo.getEmail());
            UserDetails userDetails;
            if (null != user) {
                userDetails = userDetailsService.loadUserByUsername(user.getUsername());
                user.setAddress(wxLoginVo.getUserInfo().getAddress());
                user.setAvatar(wxLoginVo.getUserInfo().getAvatar());
                user.setNickName(wxLoginVo.getUserInfo().getNickName());
                user.setSex(wxLoginVo.getUserInfo().getSex());
                user.setOpenId(openId);
                this.userNewId = user.getId();
                log.info("this.userNewId"+this.userNewId);
                sysUserMapper.updateUser(user);
            } else {
                SysUser userInfo = wxLoginVo.getUserInfo();
                userInfo.setEmail(wxLoginVo.getEmail());
                userInfo.setUserName(wxLoginVo.getUserInfo().getNickName());
                userInfo.setOpenId(openId);
                userInfo.setPassword(passwordEncoder.encode(MD5Util.md5("123456")));// 设置初始密码
                userInfo.setMember(true);
                userInfo.setAdmin(false);
                userInfo.setStatus(false);
                sysUserMapper.insertUser(userInfo);
                userNewId = userInfo.getId();
                userDetails = userDetailsService.loadUserByUsername(userInfo.getEmail());
            }
            //更新security登录用户对象
            log.info("登录成功，在security对象存入登录信息");
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);

            log.info("新的id"+userNewId);

            log.info("根据登录信息获取token");
            // 借助 jwt 生成token
            String token = tokenUtil.generateToken(userDetails);

            //4. 返回微信所需参数 token
            Map<String, String> result = new HashMap<>(16);
            result.put("openId", openId);
            result.put("sessionKey", sessionKey);
            result.put("tokenHead", tokenHead);
            result.put("token", token);
            // 返回用户信息以及档案信息
            return Result.success("微信登录成功", result);
        } catch (Exception e) {
            log.info("程序出错： --> {}", e.getMessage());
            return Result.failure("登录失败");
        }
    }

    // 根据用户输入的邮箱账号去数据库查询是否有该用户
    public Result getUserInfo(String email) {
        log.info("开始获取档案信息");
        SysUser user = sysUserMapper.findByEmail(email);
        try {
            if(user != null){
                TMember members = sysUserMapper.findMembers(user.getId());
                Map<String, Object> result = new HashMap<>();
                result.put("user", user);
                result.put("member", members);
                return Result.success("获取档案信息成功", result);
            } else {
                return Result.success("暂无档案");
            }
        } catch (Exception e){
            return Result.failure("获取失败{}"+e.getMessage());
        }
    }

    /**
     * 添加到户档案关系表中
     * @param memberNewId
     */
    public void insertUserMember(Long memberNewId){
        log.info("这里userNewId"+this.userNewId);
        sysUserMapper.insertUserMember(userNewId , memberNewId);
    }

    /**
     * 微信运动登录
     * @param code
     * @return
     */
    @Override
    public Result runLogin(String code) {
        //访问微信url
        String url = "https://api.weixin.qq.com/sns/jscode2session";
        //添加参数
        Map<String, String> map = new HashMap<>(16);
        map.put("appid", appid);
        map.put("secret", secret);
        map.put("js_code", code);
        map.put("grant_type", "authorization_code");
        try {
            //2. 根据请求码获取用户openId
            String response = HttpUtil.getResponse(url, map);
            log.info("response"+response);
            //将字符串转为Json
            JSONObject object = JSON.parseObject(response);

            //得到sessionKey
            String sessionKey = object.getString("session_key");
            log.info("微信运动---登录成功");
            return Result.success("微信运动---登录成功", sessionKey);
        } catch (Exception e) {
            log.info("程序出错： --> {}", e.getMessage());
            return Result.failure("登录失败");
        }
    }
}
